package app;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


//import utils.FileUtils;
import utils.JSONUtils;
import app.security.AppGroup;
import app.security.Profile;
import app.security.ProfileLoad;
import app.security.ResSecLevel;
import app.structure.Application;
import app.structure.MenuFrm;
import app.structure.MenuProc;
import app.structure.MenuStruct;


//import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import config.Parameters;

/**
 * Clase que carga els profiles,grupos,procediments o metodos, y aplicacions. 
 * HashMaps codificats en json en archius .cnf en config
 * 
 */
public class ApplicationManager {

	// Every profile
	private HashMap<String, Profile> hashProfile;
	// Every application group for setting security level in profiles
	private HashMap<String, AppGroup> hashGroups;
	// Every procedure or method callable from the menu
	private HashMap<String, MenuProc> hashProcs;
	// Every form callable from the menu
	private HashMap<String, MenuFrm> hashForms;
	// Every application
	private HashMap<String, Application> hashApplications;

	public ApplicationManager(boolean fillValues) {

		if (fillValues)
			fillData();
	}

	private void fillData() {

		fillApplications();
		fillAppInfo();
		fillForms();
		fillProcs();
		fillGroups();
		fillProfiles();
	}

	private void fillApplications() {
		String s = Parameters.CONFIG_PATH + "applications.cnf";
		try {
			hashApplications = JSONUtils.readFromJSONFile(s,
					new TypeToken<HashMap<String, Application>>() {
					}.getType());

		} catch (IOException | URISyntaxException e) {
			System.out.println("no sa trobat " + s);
		}
	}

	private void fillAppInfo() {

		for (Application ap : hashApplications.values()) {

			String s = Parameters.CONFIG_PATH + "mnu_" + ap.getName().trim()
					+ ".cnf";
			try {
				List<MenuStruct> readFromJSONFile = JSONUtils.readFromJSONFile(
						s, new TypeToken<List<MenuStruct>>() {
						}.getType());
				ap.setMenuStructs((List<MenuStruct>) readFromJSONFile);
			} catch (Exception e) {
				System.out.println("no sa trobat " + s);
			}
		}

	}

	private void fillForms() {
		String s = Parameters.CONFIG_PATH + "menufrms.cnf";
		try {

			hashForms = JSONUtils.readFromJSONFile(s,
					new TypeToken<HashMap<String, MenuFrm>>() {
					}.getType());

		} catch (IOException | URISyntaxException e) {
			System.out.println("no sa trobat " + s);
		}
	}

	private void fillProcs() {
		String s = Parameters.CONFIG_PATH + "menuprocs.cnf";
		try {
			hashProcs = JSONUtils.readFromJSONFile(s,
					new TypeToken<HashMap<String, MenuProc>>() {
					}.getType());
		} catch (IOException | URISyntaxException e) {
			System.out.println("no sa trobat " + s);
		}
	}

	private void fillGroups() {
		String s = Parameters.CONFIG_PATH + "appgroups.cnf";
		try {

			hashGroups = JSONUtils.readFromJSONFile(s,
					new TypeToken<HashMap<String, AppGroup>>() {
					}.getType());
		} catch (IOException | URISyntaxException e) {
			System.out.println("no sa trobat " + s);
		}
	}

	private void fillProfiles() {
		String s = Parameters.CONFIG_PATH + "profiles.cnf";
		try {

			ArrayList<ProfileLoad> prfLoads = JSONUtils.readFromJSONFile(s,
					new TypeToken<List<ProfileLoad>>() {
					}.getType());
			hashProfile = new HashMap<String,Profile>();
			for (ProfileLoad pfLd : prfLoads) {
				hashProfile.put(pfLd.name, pfLd.getProfile(this));
			}

		} catch (IOException | URISyntaxException e) {
			System.out.println("no sa trobat " + s);
		}
		fillMasterProfile();
	}

	private void fillMasterProfile() {
		Profile master = new Profile();
		master.setName("master");
		HashMap<String, Integer> masterApps = master.getApps();
		for (String appName : hashApplications.keySet()) {
			masterApps.put(appName, 6);
		}
		hashProfile.put(master.getName(), master);
	}

	// Gets a list of available applications by a profile security level
	public List<ResSecLevel> getAppsSecLevels(String profileName) {

		Profile profile = getProf(profileName);
		List<ResSecLevel> resSecLevels = new ArrayList<ResSecLevel>();

		Integer secLevel;
		ResSecLevel resSecLevel;
		HashMap<String, Integer> apps = profile.getApps();

		for (Application ap : hashApplications.values()) {

			// agafem el secLevel de la app
			secLevel = apps.get(ap.getName());

			if (secLevel != null) {
				resSecLevel = new ResSecLevel(ap.getName(), secLevel,
						ap.getIcon());
				resSecLevels.add(resSecLevel);
			}
		}
		return resSecLevels;
	}

	// Returns security level in an application from a profile
	public int getAppSecLevel(String appName, String profileName) {
		int secLevel = -1;
		Profile prf = getProf(profileName);
		Integer sLevel = prf.getApps().get(appName);
		if (sLevel.intValue() > 0)
			secLevel = sLevel.intValue();
		return secLevel;
	}

	public Application getApp(String name) {
		return hashApplications.get(name);
	}

	public MenuFrm getForm(String id) {
		return hashForms.get(id);
	}

	public MenuProc getProc(String id) {
		return hashProcs.get(id);
	}

	public AppGroup getGroup(String name) {
		return hashGroups.get(name);
	}

	public Profile getProf(String name) {
		return hashProfile.get(name);
	}
}
